home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / snpd1292.zip / CHBYTES.C < prev    next >
C/C++ Source or Header  |  1992-12-26  |  7KB  |  204 lines

  1. /*
  2. **  CHBYTES.C - Change bytes in a file
  3. **
  4. **  This program searches a file for a sequence of bytes. If they are
  5. **  found, they are replaced with zeros. It was originally developed for
  6. **  a friend who needed a program to call from Paradox to remove printer
  7. **  control sequences from formatted print files. The requirements were
  8. **  1) since it is called by another program, all status has to be returned
  9. **  in the errorlevel with no screen messages allowed, and 2) The file must
  10. **  remain the same length, so the deleted sequences must only be replaced
  11. **  with ASCII NULs.
  12. **
  13. **  Syntax: CHBYTES filename pattern_1 [pattern_2 [...pattern_N]]
  14. **  where:  Each pattern is a comma-separated list of bytes, each of which
  15. **          may be of the following forms:
  16. **          C    - Any single character will be treated as literal.
  17. **          XXh  - "XX" will be interpreted as a hexidecimal number (both
  18. **                 1- and 2-digit hex numbers are allowed).
  19. **          NNNd - "NNN" will be interpreted as a decimal number (both
  20. **                 1-, 2-, and 3-digit decimal numbers are allowed).
  21. **
  22. **  e.g.    CHBYTES printer.fil 12d 1bh,[,3,x
  23. **          would zero out form feeds and the escape sequence "[3x"
  24. **
  25. **  Returns: 0 - Success
  26. **           1 - No filename
  27. **           2 - No arguments
  28. **           3 - Error opening file
  29. **           4 - Not enough memory
  30. **           5 - Bad argument
  31. **           6 - Error reading file
  32. **           7 - Error writing file
  33. **
  34. **  Public domain by Bob Stout
  35. */
  36.  
  37. #include <stdio.h>
  38. #include <stdlib.h>
  39. #include <string.h>
  40. #include <ctype.h>
  41.  
  42. #ifdef __ZTC__
  43.  int _okbigbuf = 0;
  44. #endif
  45.  
  46. #define LAST_CHAR(s) (((char *)(s))[strlen((char *)(s)) - 1])
  47.  
  48. #ifndef max
  49.  #define max(x,y) (((x) >= (y)) ? (x) : (y))
  50. #endif
  51.  
  52. typedef enum {ERROR = -1, SUCCESS, FALSE = 0, TRUE} LOGICAL;
  53.  
  54. int bufsize;
  55.  
  56. struct {
  57.       char pattern[40];                         /* pattern to find      */
  58.       int numbytes;                             /* length of pattern    */
  59. } search[40];
  60.  
  61. int main (int argc, char *argv[])
  62. {
  63.       FILE *fp  = NULL;
  64.       char *buf = NULL, *getbuf(void);
  65.       fpos_t rpos;
  66.       int i, patterns, max_bytes = 0;
  67.       LOGICAL hex2char(const char *, char *);
  68.  
  69.       if (2 > argc)                             /* no filename          */
  70.             return 1;
  71.       if (3 > argc)                             /* no argument          */
  72.             return 2;
  73.       if (NULL == (fp = fopen(argv[1], "r+b")))
  74.             return 3;                           /* file open error      */
  75.       if (NULL == (buf = getbuf()))
  76.             return 4;                           /* no memory for buffer */
  77.  
  78.       patterns = argc - 2;                      /* process arguments    */
  79.       for (i = 2; i < argc; ++i)
  80.       {
  81.             char *p, *ptr;
  82.  
  83.             if (NULL != (ptr = strtok(argv[i], ",")))
  84.             {
  85.                   p = search[i - 2].pattern;
  86.                   do
  87.                   {
  88.                         search[i - 2].numbytes++;
  89.                         if (1 == strlen(ptr))
  90.                         {
  91.                               *p++ = *ptr;
  92.                               continue;
  93.                         }
  94.                         switch (toupper(LAST_CHAR(ptr)))
  95.                         {
  96.                         case 'D':
  97.                               LAST_CHAR(ptr) = '\0';
  98.                               *p++ = (char)atoi(ptr);
  99.                               break;
  100.                         case 'H':
  101.                               LAST_CHAR(ptr) = '\0';
  102.                               if (ERROR == hex2char(ptr, p++))
  103.                                     return 5;
  104.                               break;
  105.                         default:
  106.                               return 5;
  107.                         }
  108.                   } while (NULL != (ptr = strtok(NULL, ",")));
  109.                   *p = '\0';
  110.                   max_bytes = max(max_bytes, search[i - 2].numbytes);
  111.             }
  112.             else  return 5;
  113.       }
  114.  
  115.       fgetpos(fp, &rpos);                       /* save where we are    */
  116.       while (1)
  117.       {
  118.             int bytes, n;
  119.             LOGICAL modified;
  120.  
  121.             if (max_bytes > (bytes = (int)fread(buf, 1, bufsize, fp)))
  122.             {
  123.                   if (0 == bytes && !feof(fp))
  124.                         return 6;               /* something's wrong!   */
  125.                   else  break;                  /* all done!            */
  126.             }
  127.             for (n = 0, modified = FALSE; n < patterns; ++n)
  128.             {
  129.                   /* check each pattern in turn                         */
  130.  
  131.                   for (i = 0; i < (bytes - max_bytes + 1); ++i)
  132.                   {
  133.                         int j;
  134.  
  135.                         if (buf[i] != *(search[n].pattern))
  136.                               continue;
  137.                         if (SUCCESS != strncmp(&buf[i],
  138.                               search[n].pattern, search[n].numbytes))
  139.                         {
  140.                               continue;
  141.                         }
  142.  
  143.                         /* found one! replace it in the buffer          */
  144.  
  145.                         for (j = 0; j < search[n].numbytes; ++j, ++i)
  146.                               buf[i] = '\0';
  147.                         modified = TRUE;
  148.                   }
  149.             }
  150.             if (modified)                       /* write changes, if any*/
  151.             {
  152.                   fpos_t wpos = rpos;
  153.  
  154.                   fsetpos(fp, &wpos);
  155.                   if (bytes != (int)fwrite(buf, 1, bytes, fp))
  156.                         return 7;
  157.                   fsetpos(fp, &rpos);
  158.             }
  159.             rpos += bytes - max_bytes + 1;      /* get another buffer   */
  160.             fsetpos(fp, &rpos);
  161.       }
  162.       fclose(fp);
  163.       return SUCCESS;
  164. }
  165.  
  166. /*
  167. **  Allocate the largest buffer we can
  168. */
  169.  
  170. char *getbuf(void)
  171. {
  172.       register char *buffer;
  173.  
  174.       for (bufsize = 0x4000; bufsize >= 128; bufsize >>= 1)
  175.       {
  176.             if (NULL != (buffer = (char *) malloc(bufsize)))
  177.                   return buffer;
  178.       }
  179.       return NULL;
  180. }
  181.  
  182. /*
  183. **  Convert ASCII hex char to char
  184. */
  185.  
  186. #define xdigit(c) (toupper(c) - (((c) > '9') ? 'A' - 10 : '0'))
  187.  
  188. LOGICAL hex2char(const char *hex, char *buf)
  189. {
  190.       int ch = 0;
  191.       char *p = (char *)hex;
  192.  
  193.       while(*p)
  194.       {
  195.             if (!isxdigit(*p))
  196.                   return ERROR;
  197.             ch <<= 4;
  198.             ch  += xdigit(*p);
  199.                 ++p;
  200.       }
  201.       *buf = (char)ch;
  202.       return SUCCESS;
  203. }
  204.